package com.github.natholdallas.etc

import cn.dev33.satoken.exception.NotLoginException
import cn.dev33.satoken.exception.NotPermissionException
import cn.dev33.satoken.stp.StpInterface
import cn.dev33.satoken.stp.StpUtil
import com.github.natholdallas.common.*
import com.github.natholdallas.database.User
import com.github.natholdallas.database.Users
import com.github.natholdallas.declaration.InvalidException
import com.github.natholdallas.declaration.Response
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.config.BeanDefinition
import org.springframework.beans.factory.support.BeanDefinitionRegistry
import org.springframework.boot.ApplicationArguments
import org.springframework.boot.ApplicationRunner
import org.springframework.context.annotation.AnnotationBeanNameGenerator
import org.springframework.http.HttpStatus
import org.springframework.http.HttpStatus.BAD_REQUEST
import org.springframework.stereotype.Component
import org.springframework.web.bind.MethodArgumentNotValidException
import org.springframework.web.bind.annotation.ControllerAdvice
import org.springframework.web.bind.annotation.ExceptionHandler
import java.io.File
import java.math.BigDecimal

@Component
class InitSchedule(private val users: Users) : ApplicationRunner {

    private val logger: Logger = LoggerFactory.getLogger(InitSchedule::class.java)

    override fun run(args: ApplicationArguments?) {
        if (initialize) initialize()
        logger.info("Init completed.")
    }

    private fun initialize() {
        File(imagePath).mkdirs()
        users.save(
            User(username = "admin", password = "ar1234", role = Role.ADMIN, name = "Admin"),
            User(username = "staff", password = "ar1234", role = Role.STAFF, name = "Staff"),

            User(
                username = "user",
                password = "ar1234",
                avatar = "/imgs/1.jpg",
                role = Role.USER,
                name = "Sunshine",
                balance = BigDecimal(2000),
            ),
            User(
                username = "user1",
                password = "ar1234",
                avatar = "/imgs/2.jpg",
                role = Role.USER,
                name = "NatholDallas",
                balance = BigDecimal(1000)
            ),
            User(
                username = "user2",
                password = "ar1234",
                avatar = "/imgs/3.jpg",
                role = Role.USER,
                name = "MrYe",
                balance = BigDecimal(1000)
            ),
            User(
                username = "user3",
                password = "ar1234",
                avatar = "/imgs/4.jpg",
                role = Role.USER,
                name = "MingMiss",
                balance = BigDecimal(1000)
            ),
            User(
                username = "user4",
                password = "ar1234",
                avatar = "/imgs/5.jpg",
                role = Role.USER,
                name = "XiaoYe",
                balance = BigDecimal(1000)
            ),
            User(
                username = "user5",
                password = "ar1234",
                avatar = "/imgs/6.jpg",
                role = Role.USER,
                name = "Moyoooo",
                balance = BigDecimal(1000)
            ),
            User(
                username = "user6",
                password = "ar1234",
                avatar = "/imgs/7.jpg",
                role = Role.USER,
                name = "yolu123",
                balance = BigDecimal(1000)
            ),
            User(
                username = "user7",
                password = "ar1234",
                avatar = "/imgs/8.jpg",
                role = Role.USER,
                name = "DagouJiaojiao",
                balance = BigDecimal(1000)
            ),
            User(
                username = "user8",
                password = "ar1234",
                avatar = "/imgs/9.jpg",
                role = Role.USER,
                name = "Anshanyan",
                balance = BigDecimal(1000)
            ),
            User(
                username = "user9",
                password = "ar1234",
                avatar = "/imgs/10.jpg",
                role = Role.USER,
                name = "Amongus",
                balance = BigDecimal(300)
            ),

            User(
                username = "copilot",
                password = "ar1234",
                avatar = "/imgs/11.jpg",
                role = Role.COPILOT,
                name = "John Lis",
                gender = Gender.FEMALE,
                tag = "绝地求生"
            ),
            User(
                username = "copilot1",
                password = "ar1234",
                avatar = "/imgs/12.jpg",
                role = Role.COPILOT,
                name = "Sink",
                gender = Gender.FEMALE,
                tag = "绝地求生"
            ),
            User(
                username = "copilot2",
                password = "ar1234",
                avatar = "/imgs/13.jpg",
                role = Role.COPILOT,
                name = "Pops",
                gender = Gender.FEMALE,
                tag = "绝地求生"
            ),
            User(
                username = "copilot3",
                password = "ar1234",
                avatar = "/imgs/14.jpg",
                role = Role.COPILOT,
                name = "Snumkol",
                gender = Gender.MALE,
                tag = "绝地求生"
            ),
            User(
                username = "copilot4",
                password = "ar1234",
                avatar = "/imgs/15.jpg",
                role = Role.COPILOT,
                name = "Psawjj",
                gender = Gender.MALE,
                tag = "绝地求生"
            ),
            User(
                username = "copilot5",
                password = "ar1234",
                avatar = "/imgs/16.jpg",
                role = Role.COPILOT,
                name = "Zjhookk",
                gender = Gender.MALE,
                tag = "绝地求生"
            ),
            User(
                username = "copilot6",
                password = "ar1234",
                avatar = "/imgs/17.jpg",
                role = Role.COPILOT,
                name = "Jplller",
                gender = Gender.OTHER,
                tag = "绝地求生"
            ),
            User(
                username = "copilot7",
                password = "ar1234",
                avatar = "/imgs/18.jpg",
                role = Role.COPILOT,
                name = "Snukll",
                gender = Gender.OTHER,
                tag = "求生之路"
            ),
            User(
                username = "copilot8",
                password = "ar1234",
                avatar = "/imgs/19.jpg",
                role = Role.COPILOT,
                name = "Skuller",
                gender = Gender.OTHER,
                tag = "求生之路"
            ),
            User(
                username = "copilot9",
                password = "ar1234",
                role = Role.COPILOT,
                name = "Killer",
                avatar = "/imgs/20.jpg",
                gender = Gender.OTHER,
                tag = "求生之路"
            ),
        )
    }

}

@ControllerAdvice
class GlobalExceptionHandler {

    @ExceptionHandler(NotLoginException::class)
    fun notLogin(): Response<Any> {
        StpUtil.logout()
        return Response(HttpStatus.UNAUTHORIZED)
    }

    @ExceptionHandler(NotPermissionException::class)
    fun notPermission(): Response<Any> {
        return Response(HttpStatus.FORBIDDEN)
    }

    @ExceptionHandler(MethodArgumentNotValidException::class, InvalidException::class, NoSuchElementException::class)
    fun invalid(e: Exception) = when (e) {
        is MethodArgumentNotValidException -> Response(e.allErrors.map(::resolveInvalid), BAD_REQUEST)
        is InvalidException -> Response(e.msgs, BAD_REQUEST)
        is NoSuchElementException -> Response(arrayOf("通过ID查询的东西不存在"), BAD_REQUEST)
        else -> Response(BAD_REQUEST)
    }

}

/**
 * 自定义权限加载接口实现类
 */
@Component
class StpInterfaceImpl(private val admins: Users) : StpInterface {
    override fun getPermissionList(loginId: Any?, loginType: String?): MutableList<String> {
        val user = admins.findById(loginId.toString().toLong()).get()
        return mutableListOf(user.role.name)
    }

    override fun getRoleList(loginId: Any?, loginType: String?): MutableList<String> = mutableListOf()
}


class UniqueNameGenerator : AnnotationBeanNameGenerator() {

    override fun generateBeanName(definition: BeanDefinition, registry: BeanDefinitionRegistry): String {
        return RANDOM_UUID.toString()
    }

}
